package com.rankeiot.platform.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.ZipUtil;
import com.rankeiot.core.anno.Auth;
import com.rankeiot.core.data.response.Resp;
import com.rankeiot.core.util.CollectionUtil;
import com.rankeiot.core.util.JSONUtil;
import com.rankeiot.core.util.StringUtil;
import com.rankeiot.platform.PlatformApplication;
import com.rankeiot.platform.PlatformMenu;
import com.rankeiot.platform.inner.PluginInfo;
import com.rankeiot.platform.inner.RestartEvent;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.boot.info.BuildProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.attribute.PosixFilePermission;
import java.util.*;

@Auth(PlatformMenu.PLUGINS)
@RestController
@RequiredArgsConstructor
@RequestMapping("plugins")
public class PluginsController {
    final ApplicationContext context;
    final BuildProperties buildProperties;
    final String libBasePath = "plugin";
    final String startTime= DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss");
    @GetMapping("restart")
    public Resp restart() {
        //判断docker环境
//        String dockerId = getDockerId();
//        if (dockerId == null) {
//            System.out.println("远程通过脚本重启");
//            restartByScript();
//        } else {
//            System.out.println("远程通过Docker重启");
//            RuntimeUtil.exec("/usr/bin/docker", "restart", dockerId);
//        }

        PlatformApplication.restart();
        return Resp.of(context.hashCode());
    }





    @PostMapping("context_id")
    public Resp contextId() {
        return Resp.of(context.hashCode());
    }

    /**
     * 更新文件
     *
     * @param appid
     * @param file
     * @return
     */
    @PostMapping("upload_file")
    public Resp uploadFile(String appid, MultipartFile file) throws IOException {
        File dist = new File(libBasePath, appid);
        if (!dist.exists() || !dist.isDirectory()) {
            Resp.fail("插件不存在");
        }
        File distJar = new File(dist, file.getOriginalFilename());
        //file.transferTo(distJar);
        FileUtil.writeFromStream(file.getInputStream(), distJar);
        return Resp.ok();
    }

    @PostMapping("install_jar")
    public Resp installJar(String version, String id, String name, String author, String description, MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        if (!fileName.endsWith(".jar")) {
            Resp.fail("文件格式错误");
        }
        checkPluginId(id);
        File dist = new File(libBasePath, id);
        if (dist.exists()) {
            if (!dist.isDirectory()) {
                Resp.fail("已存在同名文件");
            }
        } else {
            dist.mkdirs();
        }

        String frameworkVersion = buildProperties.getVersion();
        Map appInfo = CollectionUtil.asMap("id", id, "name", name, "version", version, "framework", frameworkVersion, "author", author, "description", description);
        PluginInfo info = new PluginInfo();
        info.setPath(dist.getPath());
        info.setProperties(appInfo);
        info.write();
        File distJar = new File(dist, fileName);
        // file.transferTo(distJar);
        FileUtil.writeFromStream(file.getInputStream(), distJar);
        return Resp.ok();
    }

    //安装插件
    @PostMapping("install")
    public Resp install(MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        if (!fileName.endsWith(".zip")) {
            Resp.fail("文件格式错误");
        }
        String frameworkVersion = buildProperties.getVersion();
        //解压到临时目录
        File tmp = Files.createTempDirectory("upload").toFile();
        try {
            ZipUtil.unzip(file.getInputStream(), tmp, Charset.defaultCharset());
            File pluginJson = new File(tmp, "plugin.json");
            if (!pluginJson.exists()) {
                Resp.fail("文件格式错误");
            }
            String pluginJsonStr = StringUtil.read(pluginJson);
            Map m = JSONUtil.parseObject(pluginJsonStr);
            String id = (String) m.get("id");
            checkPluginId(id);
            if (!Objects.equals(frameworkVersion, m.get("framework"))) {
                Resp.fail("框架版本不一致");
            }
            File dist = new File(libBasePath, id);
            if (dist.exists()) {
                if (!dist.isDirectory()) {
                    Resp.fail("已存在同名文件");
                }
                FileUtil.moveContent(tmp, dist, true);
            } else {
                if (!tmp.renameTo(dist)) {
                    dist.mkdirs();
                    FileUtil.moveContent(tmp, dist, true);
                }
            }

        } finally {
            if (tmp.exists()) {
                FileUtil.del(tmp);
            }
        }
        return Resp.ok();
    }

    private void checkPluginId(String id) {
        if (StringUtil.isEmpty(id) || id.indexOf("..") > -1) {
            Resp.fail("ID格式错误");
        }
    }

    //卸载插件
    @PostMapping("uninstall")
    public Resp uninstall(String id) {
        checkPluginId(id);
        File file = new File(libBasePath, id);
        if (file.exists()) {
            FileUtil.del(file);
        }
        return Resp.ok();
    }

    //插件列表
    @PostMapping("list")
    public Resp list() {
        File file = new File(libBasePath);
        if (!file.exists() || !file.isDirectory()) {
            return Resp.ok();
        }
        List result = new ArrayList();
        for (File f : file.listFiles()) {
            if (f.isDirectory()) {
                File pluginInfo = new File(f, "plugin.json");
                if (pluginInfo.exists()) {
                    try {
                        Map m = JSONUtil.getObjectMapper().readValue(pluginInfo, Map.class);
                        result.add(m);
                    } catch (IOException e) {
                        e.printStackTrace();
                        continue;
                    }
                }
            }
        }
        return Resp.of(result);
    }

    //插件启用/禁用
    @PostMapping("enable")
    public Resp enable(String id, boolean enable) throws IOException {
        checkPluginId(id);
        PluginInfo pluginInfo = loadPlugin(id);
        if (pluginInfo == null) {
            Resp.fail("应用不存在");
        }
        pluginInfo.getProperties().put("disabled", !enable);
        pluginInfo.write();
        return Resp.ok();
    }

    private PluginInfo loadPlugin(String pluginId) throws IOException {
        File file = new File(libBasePath);
        if (!file.exists() || !file.isDirectory()) {
            return null;
        }
        for (File f : file.listFiles()) {
            if (f.isDirectory() && f.getName().equals(pluginId)) {
                PluginInfo info = new PluginInfo();
                info.setPath(f.getPath());
                info.read();
                return info;
            }
        }
        return null;
    }

    @GetMapping("application_info")
    public Resp applicationInfo() {
        return  Resp.map().set("frameWorkVersion",buildProperties.getVersion())
                .set("lastStartTime",startTime);
    }
}
